package com.amap.flutter.location;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.provider.Settings;
import android.text.TextUtils;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.amap.api.location.AMapLocationClient;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.plugin.common.EventChannel;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.PluginRegistry;

/** 高德地图定位sdkFlutterPlugin */
public class AMapFlutterLocationPlugin implements FlutterPlugin, MethodCallHandler,
        EventChannel.StreamHandler, ActivityAware, PluginRegistry.ActivityResultListener {
  private static final String CHANNEL_METHOD_LOCATION = "amap_flutter_location";
  private static final String CHANNEL_STREAM_LOCATION = "amap_flutter_location_stream";

  private Context mContext = null;
  private ActivityPluginBinding mActivityBinding;

  public static EventChannel.EventSink mEventSink = null;
  private MethodChannel.Result _result;


  private Map<String, AMapLocationClientImpl> locationClientMap = new ConcurrentHashMap<String, AMapLocationClientImpl>(2);

  @Override
  public void onMethodCall(MethodCall call, Result result) {
    switch (call.method) {
      case "updatePrivacyStatement":
        updatePrivacyStatement((Map)call.arguments);
        result.success(true);
        break;
      case "setApiKey":
        setApiKey((Map) call.arguments);
        result.success(true);
        break;
      case "setLocationOption":
        setLocationOption((Map) call.arguments);
        result.success(true);
        break;
      case "startLocation":
        startLocation((Map) call.arguments);
        result.success(true);
        break;
      case "stopLocation":
        stopLocation((Map) call.arguments);
        result.success(true);
        break;
      case "destroy":
        destroy((Map) call.arguments);
        result.success(true);
        break;
      case "isLocationEnabled":
        result.success(Utils.isLocationEnabled(mContext));
        break;
      case "openLocationSettings": {
        _result = result;
        Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
        mActivityBinding.getActivity().startActivityForResult(intent, 100);
      }break;
//      case "startLocalNative":
        //开启 系统定位
//        LocalNative.LocalNativeManager.getInstance().start(location -> {
//          if (_event == null) {
//            AppUtils.LogI("startLocalNative callback failed for eventChannel is null");
//            return;
//          }
//          HashMap<String, Object> map = new HashMap<>();
//          map.put("#@type@#", "location");
//          if (location != null) {
//            map.put("latitude", location.getLatitude());
//            map.put("longitude", location.getLongitude());
//            //static final int MAP_TYPE_WGS84 = 1;//国际坐标系，2百度，0国测
//            map.put("mapType", 1);
//          }
//          _event.eventSink(getActivity(), map);
//        });
//        result.success(_event != null);
//        break;
//      case "stopLocalNative":
//        LocalNative.LocalNativeManager.getInstance().stop();
//        result.success(true);
//        break;
      default:
        Utils.LogI("Amap Location Plugin Method:" + call.method + " not support");
        result.notImplemented();
        break;

    }
  }

  @Override
  public void onListen(Object o, EventChannel.EventSink eventSink) {
    mEventSink = eventSink;
  }

  @Override
  public void onCancel(Object o) {
    for (Map.Entry<String, AMapLocationClientImpl> entry : locationClientMap.entrySet()) {
      entry.getValue().stopLocation();
    }
  }

  /**
   * 开始定位
   */
  private void startLocation(Map argsMap) {
    AMapLocationClientImpl locationClientImp = getLocationClientImp(argsMap);
    if (null != locationClientImp) {
      locationClientImp.startLocation();
    }
  }


  /**
   * 停止定位
   */
  private void stopLocation(Map argsMap) {
    AMapLocationClientImpl locationClientImp = getLocationClientImp(argsMap);
    if (null != locationClientImp) {
      locationClientImp.stopLocation();
    }
  }

  /**
   * 销毁
   *
   * @param argsMap
   */
  private void destroy(Map argsMap) {
    AMapLocationClientImpl locationClientImp = getLocationClientImp(argsMap);
    if (null != locationClientImp) {
      locationClientImp.destroy();

      locationClientMap.remove(getPluginKeyFromArgs(argsMap));
    }
  }

  /**
   * 设置apikey
   *
   * @param apiKeyMap
   */
  private void setApiKey(Map apiKeyMap) {
    if (null != apiKeyMap) {
      if (apiKeyMap.containsKey("android")
              && !TextUtils.isEmpty((String) apiKeyMap.get("android"))) {
        AMapLocationClient.setApiKey((String) apiKeyMap.get("android"));
      }
    }
  }

  private void updatePrivacyStatement(Map privacyShowMap) {
    if (null != privacyShowMap) {
//      Class<AMapLocationClient> locationClazz = AMapLocationClient.class;

      if (privacyShowMap.containsKey("hasContains") && privacyShowMap.containsKey("hasShow")) {
        boolean hasContains = (boolean) privacyShowMap.get("hasContains");
        boolean hasShow = (boolean) privacyShowMap.get("hasShow");
        AMapLocationClient.updatePrivacyShow(mContext, hasContains, hasShow);
//        try {
//          Method showMethod = locationClazz.getMethod("updatePrivacyShow", Context.class, boolean.class, boolean.class);;
//          showMethod.invoke(null, mContext, hasContains, hasShow);
//        } catch (Throwable e) {
////          e.printStackTrace();
//        }
      }

      if (privacyShowMap.containsKey("hasAgree")) {
        boolean hasAgree = (boolean) privacyShowMap.get("hasAgree");
        AMapLocationClient.updatePrivacyAgree(mContext, hasAgree);
//        try {
//          Method agreeMethod = locationClazz.getMethod("updatePrivacyAgree", Context.class, boolean.class);
//          agreeMethod.invoke(null, mContext, hasAgree);
//        } catch (Throwable e) {
////            e.printStackTrace();
//        }
      }
    }
  }

  /**
   * 设置定位参数
   *
   * @param argsMap
   */
  private void setLocationOption(Map argsMap) {
    AMapLocationClientImpl locationClientImp = getLocationClientImp(argsMap);
    if (null != locationClientImp) {
      locationClientImp.setLocationOption(argsMap);
    }
  }


  @Override
  public void onAttachedToEngine(FlutterPluginBinding binding) {
    if (null == mContext) {
      mContext = binding.getApplicationContext();

      /**
       * 方法调用通道
       */
      final MethodChannel channel = new MethodChannel(binding.getBinaryMessenger(), CHANNEL_METHOD_LOCATION);
      channel.setMethodCallHandler(this);

      /**
       * 回调监听通道
       */
      final EventChannel eventChannel = new EventChannel(binding.getBinaryMessenger(), CHANNEL_STREAM_LOCATION);
      eventChannel.setStreamHandler(this);
    }

  }

  @Override
  public void onDetachedFromEngine(FlutterPluginBinding binding) {
    for (Map.Entry<String, AMapLocationClientImpl> entry : locationClientMap.entrySet()) {
      entry.getValue().destroy();
    }
  }

  private AMapLocationClientImpl getLocationClientImp(Map argsMap) {
    if (null == locationClientMap) {
      locationClientMap = new ConcurrentHashMap<String, AMapLocationClientImpl>(2);
    }

    String pluginKey = getPluginKeyFromArgs(argsMap);
    if (TextUtils.isEmpty(pluginKey)) {
      return null;
    }

    if (!locationClientMap.containsKey(pluginKey)) {
      AMapLocationClientImpl locationClientImp = new AMapLocationClientImpl(mContext, pluginKey, mEventSink);
      locationClientMap.put(pluginKey, locationClientImp);
    }
    return locationClientMap.get(pluginKey);
  }

  private String getPluginKeyFromArgs(Map argsMap) {
    String pluginKey = null;
    try {
      if (null != argsMap) {
        pluginKey = (String) argsMap.get("pluginKey");
      }
    } catch (Throwable e) {
      e.printStackTrace();
    }
    return pluginKey;
  }

  @Override
  public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
    mActivityBinding = binding;
    binding.addActivityResultListener(this);
  }

  @Override
  public void onDetachedFromActivityForConfigChanges() {
    mActivityBinding.removeActivityResultListener(this);
  }

  @Override
  public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) {
    mActivityBinding = binding;
    binding.addActivityResultListener(this);
  }

  @Override
  public void onDetachedFromActivity() {
    mActivityBinding.removeActivityResultListener(this);
    mActivityBinding = null;
  }

  @Override
  public boolean onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    if (requestCode == 100) {
      _result.success(Utils.isLocationEnabled(mContext));
      return true;
    }
    return false;
  }
}
